
"""
    pycoopiler - a compiler developed for PCS2056 course (Compilers) at Poli-USP
    Copyright (C) 2008 Andre Felipe Santos    
    Copyright (C) 2008 Rodrigo Rodrigues da Silva

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
"""

import logging
import time

class codegen:
    
    def __init__(self, _file):
        self.f = _file
        self.SEPARATOR = " =============================================================="
        self.SEMICOLON = ";"
        self.code = '; ----------\n; CODE AREA\n; ----------\n'
        self.data = '; ----------\n; DATA AREA\n; ----------\n'
        self.header = self.SEMICOLON + self.SEPARATOR + "\n" +\
                self.SEMICOLON + " " + self.f.name + "\n" +\
                self.SEMICOLON + " generated " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " by pycoopiler \n" +\
                self.SEMICOLON + self.SEPARATOR + "\n" + self.SEMICOLON + "\n"
   
    def write_file(self):
        self.f.write(self.header)
        self.f.write(self.code)
        self.f.write(self.data)
    
    def write_inst(self, oper, *args):
        self.code = self.code + self.write_code(oper, *args)
        
    def write_data(self, oper, *args):
        self.data = self.data + self.write_code(oper, *args)
    
    def write_code(self, oper, *args):
        l = len(args)        
        logging.debug("len = %s", l)
        logging.debug("oper = %s", oper)
        if l==1:            
            logging.debug("arg = %s", args[0])
            line = "\t \t" + oper + args[0] + "\n"
        elif l==2:         
            logging.debug("arg = %s", args[0])            
            logging.debug("label = %s", args[1])
            line = args[1] + "\t" + oper + args[0] + "\n"
        else: raise Exception("Invalid instruction!")
        logging.debug("codegen: " + line)
        return line

    def orig(self, *args):
        self.write_inst("@  ", *args)
        
    def end(self, *args):
        self.write_inst("#  ", *args)
        
    def const(self, *args):
        self.write_data("K  ", *args)
        
    def res(self, *args):
        self.write_inst("$  ", *args)
            
    def jump(self, *args):
        self.write_inst("JP ", *args)
    
    def jzero(self, *args):
        self.write_inst("JZ ", *args)
        
    def jneg(self, *args):
        self.write_inst("JN ", *args)
        
    def lval(self, *args):
        self.write_inst("LV ", *args)
        
    def add(self, *args):
        self.write_inst("+  ", *args)
        
    def mul(self, *args):
        self.write_inst("*  ", *args)
        
    def sub(self, *args):
        self.write_inst("-  ", *args)
        
    def div(self, *args):
        self.write_inst("/  ", *args)
        
    def load(self, *args):
        self.write_inst("LD ", *args)
        
    def save(self, *args):
        self.write_inst("MM ", *args)
        
    def call(self, *args):
        self.write_inst("SC ", *args)
        
    def ret(self, *args):
        self.write_inst("RS ", *args)
        
    def halt(self, *args):
        self.write_inst("HM ", *args)
        
    def get(self, *args):
        self.write_inst("GD ", *args)
        
    def put(self, *args):
        self.write_inst("PD ", *args)
        
    def os(self, *args):
        self.write_inst("OS ", *args)
        
    